package cn.fansunion.concurrent.executorservice;

import java.util.Arrays;
import java.util.Collections;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
 * CompletionService,先获得，最快得到结果的那个线程的值
 * pool方法，可以设置超时时间
 *
 */
public class FutureTaskTest3 {

	public static void main(String[] args) {
		// 【强制】线程池不允许使用 Executors ExecutorsExecutors
		// 去创建，而是通过 去创建，而是通过 去创建，而是通过 ThreadPoolExecutor
		// ThreadPoolExecutor的方式，这样 的方式，这样 的处理方式让写同学更加明确线程池运行规则，避资源耗尽风险。
		int nThreads = 5;
		ThreadPoolExecutor executor = new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
				new LinkedBlockingQueue<Runnable>(1000));
		CompletionService<Integer> completionService= new ExecutorCompletionService<Integer>(executor);
		int maxIndex = 100;
		//1到100求和
		for (int index = 1; index <= maxIndex; index++) {
			Integer num = index;
			System.out.println(String.format("index:%s,num=%s", index,num));
			Callable<Integer> callable = new Callable<Integer>() {

				public Integer call() throws Exception {
					//让少部分超时
					int maxSleepNum = 350;
					Integer sleepNum = new Random().nextInt(maxSleepNum);
					System.out.println(String.format("SleepNum:%s", sleepNum));
					//模拟计算时间，比如从远程查询数据
					Thread.sleep(sleepNum);
					return num;
				}

			};
			//Future<Integer> task = new FutureTask<>(callable);
			if(!executor.isShutdown()){
				completionService.submit(callable);
			}
		}
		//所有成功返回的num
		Integer[] taskNumArray = new Integer[maxIndex];
		for (int index = 1; index <= maxIndex; index++) {
			try {
				//等待下1个完成的任务，然后删除，但是最多等待一定的时间
				Future<Integer> future = completionService.poll(100, TimeUnit.MILLISECONDS);
				//模拟100毫秒，方便模拟超时，程序快点执行
				if(future==null){
					break;
				}
				Integer num = future.get();
				taskNumArray[index-1]=num;
				System.out.println(String.format("num=%s,成功返回1个数据",num));
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}

		}	
		executor.shutdownNow();
		Integer sum = 0;
		//Collections.sort(Arrays.asList(taskNumArray));
		//System.out.println(taskNumArray);
		for(Integer num:taskNumArray){
			//超时的那几个，么有值，位置是空的
			if(num != null){
				System.out.print(num+",");
				sum+= num;
			}
		}
		System.out.println();
		System.out.println(String.format("sum=%s", sum));
	}

}
